/*
 * DataNode.java
 */

package xq.ide.node;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.util.Enumeration;
import java.util.List;
import java.util.Vector;
import javax.swing.tree.TreeNode;

/**
 *
 * @author ThorntonRP
 */
public class DataNode implements TreeNode {

	private PropertyDescriptor property;
	private Object data;
	private String nodeName;
	private DataNode parentNode;
	private Vector<DataNode> childNodes;
	
	public DataNode(DataNode parentNode, PropertyDescriptor property) {
		this.parentNode = parentNode;
		this.nodeName = property.getDisplayName();
		this.property = property;
		if (List.class.isAssignableFrom(property.getPropertyType())) {
			try {
				List list = (List) getData();
				if (list != null) {
					childNodes = new Vector<DataNode>(list.size());
					for (int i = 0; i < list.size(); i++) {
						DataNode childNode = new DataNode(list.get(i));
						childNode.parentNode = this;
						childNodes.add(childNode);
					}
				}
			} catch (Exception ex) {
				ex.printStackTrace();
			}
		}
	}
	
	public DataNode(Object data) {
		this.parentNode = null;
		this.data = data;
		this.nodeName = null;
		
		if (data != null) {
			try {
				BeanInfo bean = Introspector.getBeanInfo(data.getClass());
				PropertyDescriptor[] properties = bean.getPropertyDescriptors();
				for (PropertyDescriptor pd : properties) {
					if (!pd.getName().equals("class")) {
						if (childNodes == null) {
							childNodes = new Vector<DataNode>();
						}
						childNodes.add(new DataNode(this, pd));
					}
				}
			} catch (Exception ex) {
				ex.printStackTrace();
			}
		}
	}
	
	public Object getData() throws Exception {
		if (data == null) {
			data = property.getReadMethod().invoke(parentNode.getData());
		}
		return data;
	}
	
	@Override
	public TreeNode getChildAt(int childIndex) {
		return childNodes.get(childIndex);
	}

	@Override
	public int getChildCount() {
		return isLeaf() ? 0 : childNodes.size();
	}

	@Override
	public TreeNode getParent() {
		return parentNode;
	}

	@Override
	public int getIndex(TreeNode node) {
		return childNodes.indexOf(node);
	}

	@Override
	public boolean getAllowsChildren() {
		return childNodes != null;
	}

	@Override
	public boolean isLeaf() {
		return childNodes == null;
	}

	@Override
	public Enumeration children() {
		return childNodes.elements();
	}

	@Override
	public String toString() {
		if (nodeName == null) {
			if (data != null) {
				return data.getClass().getName();
			} else {
				return "";
			}
		} else {
			StringBuilder sb = new StringBuilder();
			sb.append(nodeName);
			if (property != null) {
				if (property.getPropertyType().equals(String.class) ||
					property.getPropertyType().equals(Long.class) ||
					property.getPropertyType().equals(Integer.class)) {
					try {
						sb.append("=").append(getData());
					} catch (Exception ex) {
						ex.printStackTrace();
					}
				} else {
					sb.append(" (").append(property.getPropertyType().getName()).append(")");
					if (List.class.isAssignableFrom(property.getPropertyType())) {
						try {
							List list = (List) getData();
							if (list != null) {
								sb.append(" [size=").append(list.size()).append("]");
							}
						} catch (Exception ex) {
							ex.printStackTrace();
						}
					}
				}
			}
			return sb.toString();
		}
	}
}
